﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;

namespace YArchitech.Revit
{
	public class SearchBranch
	{
		public SearchBranch(ElementNode elemNode)
		{
			this.rootElement = elemNode;
			this.element = elemNode.Element;
		}

		public SearchBranch(ElementNode elemNode, List<ElementType> searchType)
		{
			this.rootElement = elemNode;
			this.element = elemNode.Element;
			this.searchElem = searchType;
		}

		public SearchBranch(UIDocument uiDoc)
		{
			this.uiDoc = uiDoc;
			this.doc = uiDoc.Document;
			this.sel = uiDoc.Selection;
		}

		public SearchBranch(ElementType searchType, UIDocument uiDoc)
		{
			this.uiDoc = uiDoc;
			this.doc = uiDoc.Document;
			this.sel = uiDoc.Selection;
			this.systemTypeCheck = true;
			this.searchElem.Add(ElementType.FamilyInstance);
			this.AddSearchType(searchType);
		}

		public SearchBranch(ElementType searchType1, ElementType searchType2, UIDocument uiDoc)
		{
			this.uiDoc = uiDoc;
			this.doc = uiDoc.Document;
			this.sel = uiDoc.Selection;
			this.systemTypeCheck = true;
			this.searchElem.Add(ElementType.FamilyInstance);
			this.AddSearchType(searchType1);
			this.AddSearchType(searchType2);
		}

		public void PickFirstElement(ISelectionFilter selectionFilter, string tip)
		{
			if (this.uiDoc != null)
			{
				Reference reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, selectionFilter, tip);
				Element element = this.doc.GetElement(reference);
				XYZ globalPoint = reference.GlobalPoint;
				this.element = element;
				ConnectorSetIterator csi = new ElementNode(element).GetCSI();
				Connector connector = null;
				double num = 10000.0;
				while (csi.MoveNext())
				{
					object obj = csi.Current;
					Connector connector2 = obj as Connector;
					if (connector2 != null)
					{
						double num2 = globalPoint.DistanceTo(connector2.Origin);
						if (num2 < num)
						{
							num = num2;
							connector = connector2;
						}
					}
				}
				this.rootElement = new ElementNode(element, connector);
				return;
			}
			throw new Exception("请正确构造类");
		}

		public void PickFirstNearElement(ISelectionFilter selectionFilter, string tip)
		{
			if (this.uiDoc != null)
			{
				Reference reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, selectionFilter, tip);
				Element element = this.doc.GetElement(reference);
				XYZ globalPoint = reference.GlobalPoint;
				this.element = element;
				ConnectorSetIterator csi = new ElementNode(element).GetCSI();
				Connector connector = null;
				double num = 0.0;
				while (csi.MoveNext())
				{
					object obj = csi.Current;
					Connector connector2 = obj as Connector;
					if (connector2 != null)
					{
						double num2 = globalPoint.DistanceTo(connector2.Origin);
						if (num2 > num)
						{
							num = num2;
							connector = connector2;
						}
					}
				}
				this.rootElement = new ElementNode(element, connector);
				return;
			}
			throw new Exception("请正确构造类");
		}

		public SearchBranch(Element elem)
		{
			this.element = elem;
		}

		public SearchBranch(Element elem, ElementType searchType)
		{
			this.element = elem;
			this.systemTypeCheck = true;
			this.searchElem.Add(ElementType.FamilyInstance);
			this.AddSearchType(searchType);
		}

		public SearchBranch(Element elem, ElementType searchType1, ElementType searchType2)
		{
			this.element = elem;
			this.systemTypeCheck = true;
			this.searchElem.Add(ElementType.FamilyInstance);
			this.AddSearchType(searchType1);
			this.AddSearchType(searchType2);
		}

		public SearchBranch(Element elem, ElementType searchType1, ElementType searchType2, ElementType searchType3)
		{
			this.element = elem;
			this.systemTypeCheck = true;
			this.searchElem.Add(ElementType.FamilyInstance);
			this.AddSearchType(searchType1);
			this.AddSearchType(searchType2);
			this.AddSearchType(searchType3);
		}

		public SearchBranch(Element elem, List<ElementType> searchType)
		{
			this.element = elem;
			this.systemTypeCheck = true;
			this.searchElem = searchType;
		}

		public bool DoSearch()
		{
			if (this.element == null)
			{
				throw new Exception("请正确构造类");
			}
			bool result;
			try
			{
				this.InitRootElement();
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public bool DoSearch(ElementNode Node)
		{
			this.element = Node.Element;
			this.rootElement = Node;
			if (this.element == null)
			{
				throw new Exception("请正确构造类");
			}
			bool result;
			try
			{
				this.InitRootElement();
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private void AddSearchType(ElementType searchType)
		{
			if (searchType == ElementType.Duct || ElementType.FlexDuct == searchType)
			{
				this.searchElem.Add(ElementType.Duct);
				this.searchElem.Add(ElementType.FlexDuct);
				return;
			}
			if (ElementType.Pipe == searchType || ElementType.FlexPipe == searchType)
			{
				this.searchElem.Add(ElementType.Pipe);
				this.searchElem.Add(ElementType.FlexPipe);
				return;
			}
			this.searchElem.Add(searchType);
		}

		private void InitRootElement()
		{
			if (this.rootElement == null)
			{
				this.rootElement = new ElementNode(this.element);
			}
			this.GetRecursiveList(this.rootElement);
		}

		private bool ElementIsExist(Element elem)
		{
			using (List<Element>.Enumerator enumerator = this.allElement.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current.Id == elem.Id)
					{
						return true;
					}
				}
			}
			this.allElement.Add(elem);
			return false;
		}

		private void GetRecursiveList(ElementNode previewElementNode)
		{
			if (previewElementNode.Type == ElementType.Equiment && !this.searchElem.Contains(ElementType.Equiment))
			{
				previewElementNode.Next = null;
				if (previewElementNode.SubElementNode != null)
				{
					previewElementNode.SubElementNode.Clear();
				}
				if (previewElementNode.SubConnectors != null)
				{
					previewElementNode.SubConnectors.Clear();
				}
				return;
			}
			if (previewElementNode.ConnectorOut == null)
			{
				if (previewElementNode.SubConnectors == null)
				{
					return;
				}
				foreach (Connector connector in previewElementNode.SubConnectors)
				{
					Connector connectConnector = this.GetConnectConnector(connector);
					if (connectConnector != null)
					{
						ElementNode elementNode = new ElementNode(connectConnector.Owner, connectConnector);
						if (this.CheckSystemType(elementNode))
						{
							previewElementNode.SubElementNode.Add(elementNode);
						}
					}
				}
				IEnumerator<ElementNode> enumerator2 = previewElementNode.SubElementNode.GetEnumerator();
				{
					while (enumerator2.MoveNext())
					{
						ElementNode elementNode2 = enumerator2.Current;
						elementNode2.Preview = previewElementNode;
						this.GetRecursiveList(elementNode2);
					}
					return;
				}
			}
			Connector connectConnector2 = this.GetConnectConnector(previewElementNode.ConnectorOut);
			if (connectConnector2 == null)
			{
				if (previewElementNode.SubConnectors != null)
				{
					foreach (Connector connector2 in previewElementNode.SubConnectors)
					{
						Connector connectConnector3 = this.GetConnectConnector(connector2);
						if (connectConnector3 != null)
						{
							ElementNode elementNode3 = new ElementNode(connectConnector3.Owner, connectConnector3);
							if (this.CheckSystemType(elementNode3))
							{
								previewElementNode.SubElementNode.Add(elementNode3);
							}
						}
					}
					foreach (ElementNode elementNode4 in previewElementNode.SubElementNode)
					{
						elementNode4.Preview = previewElementNode;
						this.GetRecursiveList(elementNode4);
					}
				}
				return;
			}
			ElementNode elementNode5 = new ElementNode(connectConnector2.Owner, connectConnector2);
			if (!this.CheckSystemType(elementNode5))
			{
				return;
			}
			previewElementNode.Next = elementNode5;
			elementNode5.Preview = previewElementNode;
			this.GetRecursiveList(elementNode5);
			if (previewElementNode.SubConnectors != null)
			{
				foreach (Connector connector3 in previewElementNode.SubConnectors)
				{
					Connector connectConnector4 = this.GetConnectConnector(connector3);
					if (connectConnector4 != null)
					{
						ElementNode elementNode6 = new ElementNode(connectConnector4.Owner, connectConnector4);
						if (this.CheckSystemType(elementNode6))
						{
							previewElementNode.SubElementNode.Add(elementNode6);
						}
					}
				}
				foreach (ElementNode elementNode7 in previewElementNode.SubElementNode)
				{
					elementNode7.Preview = previewElementNode;
					this.GetRecursiveList(elementNode7);
				}
			}
		}

		private bool CheckSystemType(ElementNode elem)
		{
			ElementType type = elem.Type;
			bool flag = false;
			if (!this.systemTypeCheck)
			{
				flag = true;
			}
			else
			{
				foreach (ElementType elementType in this.searchElem)
				{
					if (type == elementType)
					{
						flag = true;
						break;
					}
				}
			}
			if (flag && this.ElementIsExist(elem.Element))
			{
				throw new Exception("搜索为环路，请检查！");
			}
			return flag;
		}

		private Connector GetConnectConnector(Connector connector)
		{
			Connector result = null;
			if (connector != null && connector.IsConnected)
			{
				ConnectorSetIterator connectorSetIterator = connector.AllRefs.ForwardIterator();
				while (connectorSetIterator.MoveNext())
				{
					object obj = connectorSetIterator.Current;
					Connector connector2 = obj as Connector;
					if (connector2 != null && connector2.Owner.UniqueId != connector.Owner.UniqueId && (connector2.ConnectorType == 1 || connector2.ConnectorType == 2 || connector2.ConnectorType == 19))
					{
						result = connector2;
						break;
					}
				}
			}
			return result;
		}

		public ElementNode GetListRoot()
		{
			return this.rootElement;
		}

		public Element GetElementIn()
		{
			return this.element;
		}

		private TreeView GetTree()
		{
			TreeView result = null;
			this.Display(this.rootElement);
			return result;
		}

		private TreeView GetTree(Selection sel, Document doc)
		{
			TreeView result = null;
			this.sel = sel;
			this.doc = doc;
			this.Display(this.rootElement);
			MessageBox.Show(this.tempi.ToString());
			return result;
		}

		private void Display(ElementNode en)
		{
			if (en == null)
			{
				return;
			}
			MessageBox.Show(en.Type.ToString());
			this.tempi++;
			if (this.tempi == 1)
			{
				RevitVersionFuncs.AddToSelection(this.sel, en.Element);
			}
			this.doc.Regenerate();
			this.Display(en.Next);
			if (en.SubElementNode != null)
			{
				foreach (ElementNode en2 in en.SubElementNode)
				{
					this.Display(en2);
				}
			}
		}

		public void GetAllElement(ElementNode en, ref List<MEPCurve> listElement)
		{
			if (en == null)
			{
				return;
			}
			Element element = en.Element;
			if (element is Conduit || element is CableTray || element is Pipe || element is Duct)
			{
				listElement.Add((MEPCurve)element);
			}
			this.GetAllElement(en.Next, ref listElement);
			if (en.SubElementNode != null)
			{
				foreach (ElementNode en2 in en.SubElementNode)
				{
					this.GetAllElement(en2, ref listElement);
				}
			}
		}

		private List<Element> allElement = new List<Element>();

		private List<ElementType> searchElem = new List<ElementType>();

		private Element element;

		private ElementNode rootElement;

		private bool systemTypeCheck;

		private Document doc;

		private UIDocument uiDoc;

		private Selection sel;

		private int tempi;
	}
}
